﻿/*************************************************************************
 *  Copyright © 2023-2030 Administrator. All rights reserved.
 *------------------------------------------------------------------------
 *  公司：DefaultCompany
 *  项目：CustomPackageManager
 *  文件：CustomPackageManager.cs
 *  作者：Administrator
 *  日期：2024/9/28 22:10:41
 *  功能：Nothing
*************************************************************************/

using UnityEditor;
using UnityEngine;
using System.IO;
using System;
using System.Linq;
using SVNPackageManager.Runtime;
using UnityEditor.IMGUI.Controls;
using System.Collections.Generic;
using System.Diagnostics;

namespace SVNPackageManager.Editor
{
    public class SVNPackageManager : EditorWindow
    {
        public static SVNPackageManager instace;

        #region Style
        public GUIStyle basePackageItemStyle;
        public GUIStyle packageSourceBgStyle;
        public GUIStyle packageSourceBtnStyle;
        public GUIStyle packageGroupBtnStyle;
        public GUIStyle packageGroupBtnNormalStyle;
        public GUIStyle packageGroupBtnActiveStyle;
        public GUIStyle packageGroupBtnOutFocusStyle;
        public GUIStyle packageGroupVersionActiveStyle;
        public GUIStyle packageGroupInstallActiveStyle;
        public GUIStyle packageItemBtnStyle;
        public GUIStyle packageItemBtnNormalStyle;
        public GUIStyle packageItemBtnActiveStyle;

        public GUIStyle baseLabelStyle;
        public GUIStyle packageInfoBgStyle;
        public GUIStyle packageDisPlayNameStyle;
        public GUIStyle packageVersionStyle;
        public GUIStyle packageNameStyle;
        public GUIStyle packageDescribeStyle;
        public GUIStyle packageInstallStyle;
        public GUIStyle packageInstallPathStyle;
        public GUIStyle samplesByStyle;
        public GUIStyle samplesBtnStyle;
        #endregion

        #region Rect
        private Rect packageSourceBtnRect;
        private Rect packageSourcefolderRect;
        private Rect packageGroupBtnRect;
        private Rect packageGroupFolderRect;
        private Rect packageGroupVersionRect;
        private Rect packageItemBtnRect;
        private Rect packageItemVersionRect;

        private Rect samplesBtnRect;
        private Rect samplesfolderRect;
        #endregion

        #region public
        public Vector2 listScrollPos;
        public Vector2 packageScrollPos;

        public SVNHelper svnHelper;
        public PackageResourceManage resourceManage;
        public PackageDataProcessor packageDataProcessor;
        public PackageInstallManager packageInstallManager;
        public ScopedRegistryConfig svnScopedRegistryConfig;

        public RefreshPackageDraw refreshPackageDraw;

        public string searchText = "";
        public string updataTime = "";
        public bool samplesFolderState = false;
        public bool isInit = false;

        #endregion

        #region private
        private const float listWidth = 400;
        private const float packageItemHeight = 24;
        private Color lineColor = new Color(0.137f, 0.137f, 0.137f, 1F);
        private SearchField searchField;

        private bool validVirify = false;
        private bool isSilentRefresh = false;

        private PackageItemInfo curSelectedPackage;
        private PacakgeStateMessage curPackageState;

        #endregion

        [MenuItem("Window/SVN Package Manager")]
        public static void ShowWindow()
        {
            instace = (SVNPackageManager)GetWindow(typeof(SVNPackageManager));
            instace.titleContent = new GUIContent("SVN Package Manager", Resources.Load("Icons/SVN") as Texture2D);
            instace.minSize = new Vector2(800, 250);
            var position = instace.position;
            position.center = new Rect(0f, 0f, Screen.width, Screen.height).center;
            instace.position = position;
            instace.wantsMouseMove = true;
            instace.Show();
        }

        private void OnEnable()
        {
            EditorApplication.update += UpdateCall;

            PackageManagerInit();
        }

        private void OnDisable()
        {
            EditorApplication.update -= UpdateCall;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void PackageManagerInit()
        {
            searchField = new SearchField();

            resourceManage = new PackageResourceManage();
            resourceManage.InitResource();

            svnScopedRegistryConfig = resourceManage.svnScopedRegistryConfig;
            validVirify = svnScopedRegistryConfig.ScopedRegistryVerify();

            if (!isInit)
            {
                isInit = true;

                refreshPackageDraw = new RefreshPackageDraw(resourceManage);

                svnHelper = new SVNHelper(resourceManage);
                packageDataProcessor = new PackageDataProcessor(svnHelper, resourceManage);
                packageInstallManager = new PackageInstallManager(svnHelper, resourceManage);

                RefreshPackageList(false, false);
            }
            else
            {
                RefreshPackageList(true, true);

                //每次安装包后重新获取一下当前包和选中一下
                curSelectedPackage = packageDataProcessor.GetCurSelectedPackageByIndex();
                PingCurPackage();
            }
        }

        /// <summary>
        /// 生成窗口需要的样式
        /// </summary>
        public void GeneteStyle()
        {
            basePackageItemStyle = new GUIStyle();
            basePackageItemStyle.normal = new GUIStyleState { background = null, textColor = new Color(0.776f, 0.776f, 0.776f) };
            basePackageItemStyle.alignment = TextAnchor.MiddleLeft;
            basePackageItemStyle.fontSize = 14;

            packageSourceBgStyle = new GUIStyle();
            packageSourceBgStyle.normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.188F, 0.188F, 0.188F)) };

            packageSourceBtnStyle = new GUIStyle(basePackageItemStyle);
            packageSourceBtnStyle.fontStyle = FontStyle.Bold;

            packageGroupBtnNormalStyle = new GUIStyle(basePackageItemStyle);
            packageGroupBtnNormalStyle.fontSize = 12;

            packageGroupBtnActiveStyle = new GUIStyle(packageGroupBtnNormalStyle);
            packageGroupBtnActiveStyle.normal.background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.173f, 0.365f, 0.529f, 0.5f));

            packageGroupBtnOutFocusStyle = new GUIStyle(packageGroupBtnNormalStyle);
            packageGroupBtnOutFocusStyle.normal.background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.31f, 0.31f, 0.31f, 0.5f));

            packageGroupVersionActiveStyle = new GUIStyle();
            packageGroupVersionActiveStyle.fontSize = 12;
            packageGroupVersionActiveStyle.normal.textColor = new Color(0.776f, 0.776f, 0.776f);
            packageGroupVersionActiveStyle.alignment = TextAnchor.MiddleCenter;

            packageGroupInstallActiveStyle = new GUIStyle();
            packageGroupInstallActiveStyle.fontSize = 12;
            packageGroupInstallActiveStyle.normal.textColor = new Color(0f, 1f, 0f);
            packageGroupInstallActiveStyle.alignment = TextAnchor.MiddleCenter;

            packageItemBtnNormalStyle = new GUIStyle(packageGroupBtnNormalStyle);
            packageItemBtnNormalStyle.normal.background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.2f, 0.2f, 0.2f, 1f));
            packageItemBtnActiveStyle = new GUIStyle(packageGroupBtnActiveStyle);

            baseLabelStyle = new GUIStyle();
            baseLabelStyle.normal.textColor = new Color(0.776f, 0.776f, 0.776f);
            baseLabelStyle.fontSize = 12;

            packageDisPlayNameStyle = new GUIStyle(baseLabelStyle);
            packageDisPlayNameStyle.fontStyle = FontStyle.Bold;
            packageDisPlayNameStyle.fontSize = 20;
            packageDisPlayNameStyle.padding.left = 10;

            packageVersionStyle = new GUIStyle(packageDisPlayNameStyle);
            packageVersionStyle.fontSize = 12;

            packageNameStyle = new GUIStyle(baseLabelStyle);
            packageNameStyle.padding.left = 10;
            packageNameStyle.fontStyle = FontStyle.Italic;

            packageDescribeStyle = new GUIStyle(baseLabelStyle);
            packageDescribeStyle.wordWrap = true;
            packageDescribeStyle.padding.left = 8;

            packageInstallStyle = new GUIStyle(packageDescribeStyle);
            packageInstallStyle.fontStyle = FontStyle.Bold;

            packageInstallPathStyle = new GUIStyle(packageDescribeStyle);

            packageInfoBgStyle = new GUIStyle();
            packageInfoBgStyle.normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.188F, 0.188F, 0.188F)) };

            samplesByStyle = new GUIStyle();
            samplesByStyle.normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.188F, 0.188F, 0.188F)) };

            samplesBtnStyle = new GUIStyle();
            samplesBtnStyle.normal = new GUIStyleState { background = null, textColor = new Color(0.776f, 0.776f, 0.776f) };
            samplesBtnStyle.alignment = TextAnchor.MiddleLeft;
            samplesBtnStyle.fontSize = 14;
            samplesBtnStyle.fontStyle = FontStyle.Bold;
        }

        private void OnGUI()
        {
            GeneteStyle();

            EditorGUILayout.BeginVertical();

            DrawHeader();

            EditorGUILayout.BeginHorizontal();
            {
                DrawPackageList();

                PackageUtilityClass.DrawLineVertical_Right(lineColor);

                DrawPackageInfo();
            }
            EditorGUILayout.EndHorizontal();

            PackageUtilityClass.DrawLineHorizantal_Top(lineColor);

            DrawFooter();

            EditorGUILayout.EndVertical();
        }

        #region  绘制头部
        /// <summary>
        /// 绘制头部
        /// </summary>
        private void DrawHeader()
        {
            EditorGUILayout.BeginHorizontal(GUILayout.Height(20));

            GUILayout.FlexibleSpace();

            if (GUILayout.Button(resourceManage.settingsIcon, GUILayout.Height(18)))
            {
                SettingsService.OpenProjectSettings("Project/Svn Package Manager");
            }

            searchText = searchField.OnToolbarGUI(searchText);

            EditorGUILayout.Space();

            EditorGUILayout.EndHorizontal();
        }
        #endregion

        #region  包列表绘制
        /// <summary>
        /// 绘制包
        /// </summary>
        public void DrawPackageList()
        {
            listScrollPos = EditorGUILayout.BeginScrollView(listScrollPos, GUILayout.Width(listWidth));

            if (validVirify)
            {
                if (refreshPackageDraw.IsRefreshing && !isSilentRefresh)
                {
                    GUILayout.FlexibleSpace();
                    EditorGUILayout.BeginHorizontal();
                    GUILayout.FlexibleSpace();

                    refreshPackageDraw.DrawRefreshIcon(64);

                    GUILayout.FlexibleSpace();
                    EditorGUILayout.EndHorizontal();
                    GUILayout.FlexibleSpace();
                }
                else
                {
                    if (!string.IsNullOrEmpty(searchText))
                    {
                        List<PackageGroupInfo> groupInfos = packageDataProcessor.GetPackageGroupInfos();

                        groupInfos = groupInfos.Where((item) => item.packageGroupID.Contains(searchText)).ToList();

                        for (int i = 0; i < groupInfos.Count; i++)
                        {
                            DrawPackageGroup(groupInfos[i]);
                        }
                    }
                    else
                    {
                        List<PackageSourceInfo> packageSourceInfos = packageDataProcessor.GetPackageSourceInfos();

                        if (packageSourceInfos != null && packageSourceInfos.Count > 0)
                        {
                            EditorGUILayout.BeginVertical();
                            {
                                for (int i = 0; i < packageSourceInfos.Count; i++)
                                {
                                    DrawPackageSourceList(packageSourceInfos[i]);
                                }
                            }
                            EditorGUILayout.EndVertical();
                        }
                    }
                }
            }
            else
            {
                GUIStyle gUIStyle = new GUIStyle { alignment = TextAnchor.MiddleCenter, normal = new GUIStyleState { textColor = new Color(0.776f, 0.776f, 0.776f) } };
                GUILayout.FlexibleSpace();
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                EditorGUILayout.LabelField("请先", gUIStyle, GUILayout.Width(gUIStyle.CalcSize(new GUIContent("请先")).x));
                if (CustomEditorComponent.DrawLinkButton("设置"))
                {
                    SettingsService.OpenProjectSettings("Project/Svn Package Manager");
                }
                EditorGUILayout.LabelField("SVN账号密码和SVN地址", gUIStyle, GUILayout.Width(gUIStyle.CalcSize(new GUIContent("SVN账号密码和SVN地址")).x));
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                GUILayout.FlexibleSpace();
            }

            EditorGUILayout.EndScrollView();
        }

        /// <summary>
        /// 绘制包源列表
        /// </summary>
        /// <param name="packageSourceInfo"></param>
        private void DrawPackageSourceList(PackageSourceInfo packageSourceInfo)
        {
            DrewPackageSource(packageSourceInfo);

            PackageUtilityClass.DrawLine(lineColor, new Vector2(packageSourceBtnRect.x, packageSourceBtnRect.y + packageSourceBtnRect.height), new Vector2(packageSourceBtnRect.x + packageSourceBtnRect.width, packageSourceBtnRect.y + packageSourceBtnRect.height));

            if (packageSourceInfo.packageSourceFolderState)
            {
                for (int i = 0; i < packageSourceInfo.packageGroupInfos.Count; i++)
                {
                    DrawPackageGroup(packageSourceInfo.packageGroupInfos[i]);
                }
            }
        }

        /// <summary>
        /// 绘制包源
        /// </summary>
        /// <param name="packageSourceInfo"></param>
        private void DrewPackageSource(PackageSourceInfo packageSourceInfo)
        {
            EditorGUILayout.BeginHorizontal(packageSourceBgStyle, GUILayout.Height(packageItemHeight));
            {
                packageSourceBtnRect = GUILayoutUtility.GetRect(listWidth - 20, packageItemHeight);
                packageSourcefolderRect = new Rect(packageSourceBtnRect.x + 2, packageSourceBtnRect.y, 20, packageSourceBtnRect.height);
                packageSourceBtnStyle.padding.left = (int)(packageSourcefolderRect.x + packageSourcefolderRect.width);

                packageSourceInfo.packageSourceFolderState = EditorGUI.Foldout(packageSourcefolderRect, packageSourceInfo.packageSourceFolderState, "");
                if (GUI.Button(packageSourceBtnRect, packageSourceInfo.packageSourceName, packageSourceBtnStyle))
                {
                    packageSourceInfo.packageSourceFolderState = !packageSourceInfo.packageSourceFolderState;
                }
            }
            EditorGUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制包组
        /// 组显示的是当这个包没有安装时显示最新版本的信息
        /// 如果已经安装那么显示的是已经安装的版本信息
        /// </summary>
        /// <param name="packageGroupInfo"></param>
        private void DrawPackageGroup(PackageGroupInfo packageGroupInfo)
        {
            PackageItemInfo lastOrInstalled = null;

            PackageItemInfo installedPackage = packageDataProcessor.GetPackageGroupInstalledPackage(packageGroupInfo);
            PackageItemInfo lastPackage = packageDataProcessor.GetPackageGroupLastPackage(packageGroupInfo);

            if (installedPackage != null)
                lastOrInstalled = installedPackage;
            else if (lastPackage != null)
                lastOrInstalled = lastPackage;

            PackageConfig packageConfig = lastOrInstalled.packageConfig;
            float drawWidth = 0;
            int index = -1;

            EditorGUILayout.BeginVertical();
            EditorGUILayout.BeginHorizontal();
            {
                packageGroupBtnRect = GUILayoutUtility.GetRect(listWidth - 20, 25);
                packageGroupFolderRect = new Rect(packageGroupBtnRect.x + 10, packageGroupBtnRect.y, 20, packageGroupBtnRect.height);

                var curGroupID = packageDataProcessor.curSelectedGroupID;
                if (string.IsNullOrEmpty(curGroupID))
                    packageGroupBtnStyle = packageGroupBtnNormalStyle;
                else
                {
                    packageGroupBtnStyle = (packageGroupInfo.packageGroupID == curGroupID)
                        && (packageGroupInfo.groupIndex == packageDataProcessor.curSelectedGroupIndex)
                    ? (packageGroupInfo.packageGroupFolderState ? packageGroupBtnOutFocusStyle :
                    packageGroupBtnActiveStyle) : packageGroupBtnNormalStyle;
                }

                packageGroupBtnStyle.padding.left = (int)(packageGroupFolderRect.x + packageGroupFolderRect.width);
                GUIContent content = new GUIContent(!string.IsNullOrEmpty(packageConfig.displayName) ? packageConfig.displayName : packageConfig.name);   //显示内容

                bool folder = EditorGUI.Foldout(packageGroupFolderRect, packageGroupInfo.packageGroupFolderState, "");

                if (Event.current != null && Event.current.type == EventType.Used
                    && packageGroupFolderRect.Contains(Event.current.mousePosition))
                {
                    if (packageGroupInfo.packageGroupFolderState != folder)
                    {
                        packageGroupInfo.packageGroupFolderState = folder;

                        packageDataProcessor.curSelectedGroupID = packageGroupInfo.packageGroupID;
                        packageDataProcessor.curSelectedGroupIndex = packageGroupInfo.groupIndex;
                        packageDataProcessor.curSelectedPackageID = lastOrInstalled.packageItemID;

                        curSelectedPackage = packageDataProcessor.GetCurSelectedPackageByIndex();

                        PingCurPackage();
                    }

                    Event.current.Use();
                }

                if (GUI.Button(packageGroupBtnRect, content, packageGroupBtnStyle))
                {
                    packageDataProcessor.curSelectedGroupID = packageGroupInfo.packageGroupID;
                    packageDataProcessor.curSelectedGroupIndex = packageGroupInfo.groupIndex;
                    packageDataProcessor.curSelectedPackageID = lastOrInstalled.packageItemID;

                    curSelectedPackage = packageDataProcessor.GetCurSelectedPackageByIndex();

                    PingCurPackage();
                }

                if (installedPackage != null)
                {
                    if (installedPackage == lastPackage)
                    {
                        Rect installRect = GetPackageGroupDrawItemRect(packageGroupBtnRect, 16, 16, ref drawWidth, ref index);
                        EditorGUI.LabelField(installRect, "✓", packageGroupInstallActiveStyle);
                    }
                    else
                    {
                        Rect upgrateRect = GetPackageGroupDrawItemRect(packageGroupBtnRect, 16, 16, ref drawWidth, ref index);
                        GUIContent upgradeContent = new GUIContent(resourceManage.upgradeIcon);
                        EditorGUI.LabelField(upgrateRect, upgradeContent);
                    }
                }
                else
                {
                    Rect emptyRect = GetPackageGroupDrawItemRect(packageGroupBtnRect, 16, 16, ref drawWidth, ref index);
                    EditorGUI.LabelField(emptyRect, "", packageGroupInstallActiveStyle);
                }

                Rect localRect = GetPackageGroupDrawItemRect(packageGroupBtnRect, 36, 16, ref drawWidth, ref index);

                Rect bgRect = new Rect(localRect.x - 1, localRect.y - 1, localRect.width + 2, localRect.height + 2);

                EditorGUI.LabelField(bgRect, "", new GUIStyle
                {
                    normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, Color.white) },
                });

                EditorGUI.LabelField(localRect, "Local", new GUIStyle
                {
                    normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.1137f, 0.1177f, 0.122f)), textColor = Color.white },
                    alignment = TextAnchor.UpperCenter,
                });

                GUIContent versionContent = new GUIContent(packageConfig.version);

                packageGroupVersionRect = GetPackageGroupDrawItemRect(packageGroupBtnRect, packageGroupVersionActiveStyle.CalcSize(versionContent).x, packageGroupBtnRect.height, ref drawWidth, ref index);

                EditorGUI.LabelField(packageGroupVersionRect, versionContent, packageGroupVersionActiveStyle);
            }
            EditorGUILayout.EndHorizontal();

            if (packageGroupInfo.packageGroupFolderState)
            {
                DrawPackageItmes(packageGroupInfo);
            }

            EditorGUILayout.EndVertical();

            PackageUtilityClass.DrawLineHorizantal_Bottom(lineColor, 0, 0, 1);
        }

        /// <summary>
        /// 绘制包
        /// </summary>
        /// <param name="packageItmeInfo"></param>
        private void DrawPackageItmes(PackageGroupInfo packageItmeInfo)
        {
            for (int i = 0; i < packageItmeInfo.packageInfos.Count; i++)
            {
                PackageItemInfo packageInfo = packageItmeInfo.packageInfos[i];
                PackageConfig packageConfig = packageInfo.packageConfig;

                EditorGUILayout.BeginHorizontal();

                packageItemBtnRect = GUILayoutUtility.GetRect(listWidth - 20, 25);
                packageItemVersionRect = packageItemBtnRect;

                GUIContent packageMark = new GUIContent();

                //如果已经安装那么显示Currently installed,最新版显示Recommended,否则不显示
                if (packageInfo.isInstalled)
                    packageMark.text = "Currently installed";
                else if (packageInfo.isLast)
                    packageMark.text = "Recommended";

                var curSelectedPackageID = packageDataProcessor.curSelectedPackageID;
                if (string.IsNullOrEmpty(curSelectedPackageID))
                    packageItemBtnStyle = packageItemBtnNormalStyle;
                else
                {
                    packageItemBtnStyle = curSelectedPackageID == packageInfo.packageItemID
                        ? packageItemBtnActiveStyle : packageItemBtnNormalStyle;
                }
                packageItemBtnStyle.padding.left = (int)(packageGroupFolderRect.x + packageGroupFolderRect.width);


                if (GUI.Button(packageItemBtnRect, packageMark, packageItemBtnStyle))
                {
                    //展开的时候需要选中第一个
                    packageDataProcessor.curSelectedPackageID = packageInfo.packageItemID;

                    //当这里选中时，应该所在的组也是选中的
                    packageDataProcessor.curSelectedGroupID = packageItmeInfo.packageGroupID;
                    packageDataProcessor.curSelectedGroupIndex = packageItmeInfo.groupIndex;

                    curSelectedPackage = packageDataProcessor.GetCurSelectedPackageByIndex();

                    PingCurPackage();
                }

                float drawWidth = 0;
                int index = -1;

                Rect installRect = GetPackageGroupDrawItemRect(packageItemBtnRect, 16, 16, ref drawWidth, ref index);
                EditorGUI.LabelField(installRect, "", packageGroupInstallActiveStyle);

                Rect localRect = GetPackageGroupDrawItemRect(packageItemBtnRect, 36, 16, ref drawWidth, ref index);

                Rect bgRect = new Rect(localRect.x - 1, localRect.y - 1, localRect.width + 2, localRect.height + 2);

                EditorGUI.LabelField(bgRect, "", new GUIStyle
                {
                    normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, Color.white) },
                });

                EditorGUI.LabelField(localRect, "Local", new GUIStyle
                {
                    normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.1137f, 0.1177f, 0.122f)), textColor = Color.white },
                    alignment = TextAnchor.UpperCenter,
                });

                GUIContent versionContent = new GUIContent(packageConfig.version);

                packageItemVersionRect = GetPackageGroupDrawItemRect(packageItemBtnRect, packageGroupVersionActiveStyle.CalcSize(versionContent).x, packageItemBtnRect.height, ref drawWidth, ref index);

                EditorGUI.LabelField(packageItemVersionRect, versionContent, packageGroupVersionActiveStyle);

                EditorGUILayout.EndHorizontal();
            }
        }
        #endregion

        #region 绘制底部
        /// <summary>
        /// 绘制底部
        /// </summary>
        private void DrawFooter()
        {
            GUILayout.Space(1);
            EditorGUILayout.BeginHorizontal(GUILayout.Height(28));
            {
                EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
                {
                    EditorGUILayout.BeginVertical();

                    GUILayout.FlexibleSpace();
                    EditorGUILayout.BeginHorizontal();

                    GUILayout.Space(10);

                    if (refreshPackageDraw.IsRefreshing)
                    {
                        EditorGUILayout.BeginVertical();
                        GUILayout.FlexibleSpace();

                        refreshPackageDraw.DrawRefreshIcon(18);
                        GUILayout.FlexibleSpace();

                        EditorGUILayout.EndVertical();
                    }

                    GUIContent content = new GUIContent(updataTime);
                    GUILayout.Label(content, new GUIStyle("label") { fontStyle = FontStyle.Italic });
                    GUILayout.FlexibleSpace();

                    GUI.enabled = !refreshPackageDraw.IsRefreshing;
                    if (GUILayout.Button(resourceManage.refreshIcon, GUILayout.Width(30), GUILayout.Height(20)))
                    {
                        RefreshPackageList(false, false);
                    }

                    GUILayout.Space(10);

                    EditorGUILayout.EndHorizontal();
                    GUILayout.FlexibleSpace();
                    EditorGUILayout.EndVertical();
                }
                EditorGUILayout.EndHorizontal();

                PackageUtilityClass.DrawLineVertical_Right(lineColor);

                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.BeginVertical();
                    GUILayout.FlexibleSpace();
                    EditorGUILayout.BeginHorizontal();

                    GUILayout.FlexibleSpace();
                    if (!refreshPackageDraw.IsRefreshing)
                    {
                        DrawPackageOperateButton();
                    }

                    GUILayout.Space(10);

                    EditorGUILayout.EndHorizontal();
                    GUILayout.FlexibleSpace();
                    EditorGUILayout.EndVertical();
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndHorizontal();

            PackageUtilityClass.DrawLineHorizantal_Top(lineColor, 0, 0, -1);
        }

        /// <summary>
        /// 绘制操作按钮
        /// </summary>
        /// <param name="packageItem"></param>
        private async void DrawPackageOperateButton()
        {
            if (string.IsNullOrEmpty(packageDataProcessor.curSelectedGroupID)) return;
            PackageItemInfo installedPackage = packageDataProcessor.GetCurSelectedPackageGroupInstalledPackage();
            PackageItemInfo lastPackage = packageDataProcessor.GetCurSelectedPackageGroupLastPackage();

            if (installedPackage == null)
            {
                if (GUILayout.Button("Install"))
                {
                    curPackageState = await packageInstallManager.InstallPackage(curSelectedPackage, OnProgressUpdated);
                    if (curPackageState.isSuccess)
                        packageDataProcessor.UpdateCurSelectPackageInstallState(curPackageState.data);
                }
            }
            else
            {
                if (curSelectedPackage != null)
                {
                    if (!curSelectedPackage.isInstalled)
                    {
                        if (GUILayout.Button($"Update to {curSelectedPackage.packageConfig.version}", GUILayout.Width(100)))
                        {
                            curPackageState = await packageInstallManager.InstallPackage(curSelectedPackage, OnProgressUpdated);
                            if (curPackageState.isSuccess)
                                packageDataProcessor.UpdateCurSelectPackageInstallState(curPackageState.data);
                        }
                    }
                    else
                    {
                        //安装的版本和最新版本不一致，则显示升级按钮
                        if (!curSelectedPackage.isLast)
                        {
                            if (GUILayout.Button($"Update to {lastPackage.packageConfig.version}", GUILayout.Width(100)))
                            {
                                curPackageState = await packageInstallManager.InstallPackage(lastPackage, OnProgressUpdated);
                                if (curPackageState.isSuccess)
                                    packageDataProcessor.UpdateCurSelectPackageInstallState(curPackageState.data);
                            }
                        }

                        if (GUILayout.Button("Remove"))
                        {
                            //确认窗口
                            if (EditorUtility.DisplayDialog("Remove Package", "Are you sure you want to remove this package?", "Remove", "Cancle"))
                            {
                                CanclePingCurPackage();
                                curPackageState = await packageInstallManager.RemovePackage(curSelectedPackage);
                                if (curPackageState.isSuccess)
                                    packageDataProcessor.UpdateCurSelectPackageRemoveState();
                            }
                        }
                    }
                }
            }
        }
        #endregion

        #region 包详细信息绘制
        /// <summary>
        /// 绘制包信息
        /// </summary>
        public void DrawPackageInfo()
        {
            if (curSelectedPackage == null) return;

            PackageConfig packageConfig = curSelectedPackage.packageConfig;

            packageScrollPos = EditorGUILayout.BeginScrollView(packageScrollPos);

            //TODO:这里在安装包的时候如果有依赖没有安装那么会报错
            //在这里可以显示这个错误在这里
            if (curPackageState != null)
            {
                if (curPackageState.packageItemID == curSelectedPackage.packageItemID && !curPackageState.isSuccess)
                    EditorGUILayout.HelpBox(curPackageState.message, MessageType.Error);
            }

            EditorGUILayout.BeginVertical();

            EditorGUILayout.BeginVertical(packageInfoBgStyle, GUILayout.Height(100));
            GUIContent content = new GUIContent(!string.IsNullOrEmpty(packageConfig.displayName) ? packageConfig.displayName : packageConfig.name);   //显示内容
            EditorGUILayout.LabelField(content, packageDisPlayNameStyle);
            GUILayout.Space(10);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField($"Version {packageConfig.version}", packageVersionStyle, GUILayout.Width(100));

            Rect typeRect = GUILayoutUtility.GetRect(50, 20);

            Rect rect = new Rect(typeRect.x, typeRect.y, 36, 16);

            Rect bgRect = new Rect(typeRect.x - 1, typeRect.y - 1, 38, 18);

            EditorGUI.LabelField(bgRect, "", new GUIStyle
            {
                normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, Color.white) },
            });

            EditorGUI.LabelField(rect, "Local", new GUIStyle
            {
                normal = new GUIStyleState { background = PackageUtilityClass.CreateTexture(1, 1, new Color(0.1137f, 0.1177f, 0.122f)), textColor = Color.white },
                alignment = TextAnchor.UpperCenter,
            });

            GUILayout.FlexibleSpace();

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.LabelField(packageConfig.name, packageNameStyle);

            EditorGUILayout.BeginHorizontal();
            GUILayout.Space(10);

            DrawPackageLink(curSelectedPackage, packageConfig);

            GUILayout.FlexibleSpace();

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();

            EditorGUILayout.BeginVertical();
            GUILayout.Space(10);
            if (string.IsNullOrEmpty(packageConfig.description))
            {
                EditorGUILayout.LabelField("There is no description for this package.", packageDescribeStyle);
            }
            else
            {
                EditorGUILayout.LabelField(packageConfig.description, packageDescribeStyle);
            }


            GUILayout.Space(10);

            if (packageConfig != null && curSelectedPackage.isInstalled)
            {
                EditorGUILayout.LabelField("Installed From", packageInstallStyle);

                EditorGUILayout.LabelField($"{curSelectedPackage.resolvedPath}", packageInstallPathStyle);

                DrawSample(packageConfig);
            }

            EditorGUILayout.EndVertical();

            #region Test
            //EditorGUILayout.BeginVertical();
            //var curSelectedGroupID = packageDataProcessor.GetCurPackageGroup();
            //foreach (var group in curSelectedGroupID.packageInfos)
            //{
            //    EditorGUILayout.LabelField("packageItemID", group.packageItemID);
            //    EditorGUILayout.Toggle("isInstalled", group.isInstalled);
            //}
            //EditorGUILayout.EndVertical();
            #endregion

            EditorGUILayout.EndVertical();

            EditorGUILayout.EndScrollView();

        }

        private void DrawPackageLink(PackageItemInfo packageItem, PackageConfig packageConfig)
        {
            if (packageItem.isInstalled)
            {
                string documentationPath = $@"{packageItem.resolvedPath}\{"README.md"}";
                if (!File.Exists(documentationPath))
                    GUI.enabled = false;
                if (CustomEditorComponent.DrawLinkButton("Documentation"))
                    Process.Start("explorer.exe", $"/select, {documentationPath}");
                GUI.enabled = true;

                string changelogPath = $@"{packageItem.resolvedPath}\{"CHANGELOG.md"}";
                if (!File.Exists(changelogPath))
                    GUI.enabled = false;
                if (CustomEditorComponent.DrawLinkButton("Changelog"))
                    Process.Start("explorer.exe", $"/select, {changelogPath}");
                GUI.enabled = true;

                string licensesPath = $@"{packageItem.resolvedPath}\{"LICENSE.md"}";
                if (!File.Exists(licensesPath))
                    GUI.enabled = false;
                if (CustomEditorComponent.DrawLinkButton("Licenses"))
                    Process.Start("explorer.exe", $"/select, {licensesPath}");
                GUI.enabled = true;
            }
            else
            {
                if (string.IsNullOrEmpty(packageConfig.documentationUrl))
                    GUI.enabled = false;
                if (CustomEditorComponent.DrawLinkButton("Documentation"))
                    Application.OpenURL(packageConfig.documentationUrl);
                GUI.enabled = true;

                if (string.IsNullOrEmpty(packageConfig.changelogUrl))
                    GUI.enabled = false;
                if (CustomEditorComponent.DrawLinkButton("Changelog"))
                    Application.OpenURL(packageConfig.changelogUrl);
                GUI.enabled = true;

                if (string.IsNullOrEmpty(packageConfig.licensesUrl))
                    GUI.enabled = false;
                if (CustomEditorComponent.DrawLinkButton("Licenses"))
                    Application.OpenURL(packageConfig.licensesUrl);
                GUI.enabled = true;
            }
        }

        private void DrawSample(PackageConfig packageConfig)
        {
            if (packageConfig.samples.Count > 0)
            {
                GUILayout.Space(10);

                EditorGUILayout.BeginHorizontal(samplesByStyle, GUILayout.Height(32));
                {
                    samplesBtnRect = GUILayoutUtility.GetRect(listWidth - 20, 32);
                    samplesfolderRect = new Rect(samplesBtnRect.x + 8, samplesBtnRect.y, 20, samplesBtnRect.height);
                    samplesBtnStyle.padding.left = (int)(samplesfolderRect.x + samplesfolderRect.width);

                    samplesFolderState = EditorGUI.Foldout(samplesfolderRect, samplesFolderState, "");
                    if (GUI.Button(samplesBtnRect, "Samples", samplesBtnStyle))
                    {
                        samplesFolderState = !samplesFolderState;
                    }
                }
                EditorGUILayout.EndHorizontal();

                if (samplesFolderState)
                {
                    EditorGUI.indentLevel += 2;
                    EditorGUILayout.BeginVertical();
                    for (int i = 0; i < packageConfig.samples.Count; i++)
                    {
                        EditorGUILayout.BeginHorizontal();

                        EditorGUILayout.LabelField(packageConfig.samples[i].displayName);
                        EditorGUILayout.Space(20);
                        if (GUILayout.Button("Import", GUILayout.Width(50)))
                        {
                            SampleImportCall(curSelectedPackage, i);
                        }
                        GUILayout.FlexibleSpace();

                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.Space(10);
                    }
                    EditorGUILayout.EndVertical();
                }
            }
        }

        private void SampleImportCall(PackageItemInfo info, int index)
        {
            packageInstallManager.ImportSampleResources(info, index);
        }
        #endregion

        #region Utility方法
        private Rect GetPackageGroupDrawItemRect(Rect baseRect, float itemWidth, float itemHeight, ref float drawWidth, ref int index)
        {
            index++;
            Rect rect = new Rect(baseRect.x + baseRect.width - itemWidth - drawWidth - index * 10, baseRect.y + (baseRect.height - itemHeight) / 2, itemWidth, itemHeight);
            drawWidth += itemWidth;
            return rect;
        }

        private void PingCurPackage()
        {
            if (curSelectedPackage != null)
            {
                string packagePath = Path.Combine("Packages", curSelectedPackage.packageGroupID, "package.json");
                UnityEngine.Object jsonObj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(packagePath);
                if (jsonObj != null && curSelectedPackage.isInstalled)
                {
                    EditorGUIUtility.PingObject(jsonObj);
                    Selection.activeObject = jsonObj;
                }
                else
                {
                    // 创建一个临时对象
                    PackageInspectorInfo packageInspectorInfo = ScriptableObject.CreateInstance<PackageInspectorInfo>();
                    packageInspectorInfo.name = curSelectedPackage.packageConfig.name;
                    packageInspectorInfo.packageConfig = curSelectedPackage.packageConfig;
                    Selection.activeObject = packageInspectorInfo;
                }
            }
        }

        private void CanclePingCurPackage()
        {
            Selection.activeObject = null;
        }

        /// <summary>
        /// 进度条绘制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnProgressUpdated(object sender, SVNProgressEventArgs args)
        {
            float progress = (float)args.CompletedFiles / args.TotalFiles;

            EditorUtility.DisplayCancelableProgressBar("Check Out", $"Checking out {args.CurrentFile} {progress}", progress);

            if (args.CompletedFiles == args.TotalFiles)
                EditorUtility.ClearProgressBar();

            Repaint(); // 强制刷新窗口
        }
        #endregion

        #region 刷新包列表逻辑

        /// <summary>
        /// 初始化包列表，这里要进行缓存，避免每次都去SVN服务器拉取数据
        /// </summary>
        private async void RefreshPackageList(bool fromCache, bool silent)
        {
            if (!validVirify) return;

            refreshPackageDraw.IsRefreshing = true;

            this.isSilentRefresh = silent;

            updataTime = "Refreshing package and features...";
            await packageDataProcessor.RefreshPackageList(fromCache);

            refreshPackageDraw.IsRefreshing = false;

            updataTime = $"Last update {DateTime.Now.ToString("MMM dd, HH:mm")}";
            Repaint();
        }

        private void UpdateCall()
        {
            refreshPackageDraw.UpdateRotation();

            //这里是否可以优化，旨在刷新动画的时候刷新窗口
            if (refreshPackageDraw.IsRefreshing)
                Repaint();
        }

        #endregion
    }
}